/*
** Haaf's Game Engine 1.7
** Copyright (C) 2003-2007, Relish Games
** hge.relishgames.com
**
** hgeFont helper class header
*/


#ifndef HGEFONT_H
#define HGEFONT_H

#include "hge.h"
#include "hgesprite.h"
#include "hgefontglyph.h"

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <map>
#include <vector>

#include <ft2build.h>
#include FT_FREETYPE_H


#define HGETEXT_LEFT		0
#define HGETEXT_RIGHT		1
#define HGETEXT_CENTER		2
#define HGETEXT_HORZMASK	0x03

#define HGETEXT_TOP			0
#define HGETEXT_BOTTOM		4
#define HGETEXT_MIDDLE		8
#define HGETEXT_VERTMASK	0x0C

// amount of bits in a uint
#define BITS_PER_UINT		(sizeof (UINT) * 8)
// must be a power of two
#define GLYPHS_PER_PAGE		256
// Pixels to put between glyphs
#define INTER_GLYPH_PAD_SPACE 2
// A multiplication coefficient to convert FT_Pos values into normal floats
#define FT_POS_COEF  (1.0/64.0)

/*
** HGE Font class
*/
class hgeFont
{
public:
	hgeFont(const char *filename, bool bMipmap=false);
	~hgeFont();

	void		Render(float x, float y, int align, const char *string);
	void		printf(float x, float y, int align, const char *format, ...);
	void		printfb(float x, float y, float w, float h, int align, const char *format, ...);

	void		SetColor(DWORD col);
	void		SetZ(float z);
	void		SetBlendMode(int blend);
	void		SetScale(float scale) {fScale=scale;}
	void		SetProportion(float prop) { fProportion=prop; }
	void		SetRotation(float rot) {fRot=rot;}
	void		SetTracking(float tracking) {fTracking=tracking;}
	void		SetSpacing(float spacing) {fSpacing=spacing;}

	DWORD		GetColor() const {return dwCol;}
	float		GetZ() const {return fZ;}
	int			GetBlendMode() const {return nBlend;}
	float		GetScale() const {return fScale;}
	float		GetProportion() const { return fProportion; }
	float		GetRotation() const {return fRot;}
	float		GetTracking() const {return fTracking;}
	float		GetSpacing() const {return fSpacing;}

	float		GetHeight() const { return fHeight; }
	float		GetStringWidth(const char *string, bool bMultiline=true) const;
	
	void		Free();

private:
	hgeFont();
	hgeFont(const hgeFont &fnt);
	hgeFont&	operator= (const hgeFont &fnt);

	char*		_get_line(char *file, char *line);

	static HGE	*hge;
	static char	buffer[1024];

	float		fHeight;
	float		fScale;
	float		fProportion;
	float		fRot;
	float		fTracking;
	float		fSpacing;

	DWORD		dwCol;
	float		fZ;
	int			nBlend;
	
	char		m_facename[1024];
	FT_Face     m_face;

	//! Definition of CodepointMap type.
	typedef std::map<UINT32, hgeFontGlyph> CodepointMap;
	//! Contains mappings from code points to Image objects
	CodepointMap m_cp_map;

	//! Maximal codepoint for font glyphs
	UINT32		m_maxCodepoint;
	//! maximal font ascender (pixels above the baseline)
	float		m_ascender;
	//! maximal font descender (negative pixels below the baseline)
	float		m_descender;
	//! (ascender - descender) + linegap
	float		m_height;
	//! True if the font should be rendered as anti-alaised by freeType.
	bool		m_antiAliased;

	/*!
	This bitmap holds information about loaded 'pages' of glyphs.
	A glyph page is a set of 256 codepoints, starting at 256-multiples.
	For example, the 1st glyph page is 0-255, fourth is 1024-1279 etc.
	When a specific glyph is required for painting, the corresponding
	bit is checked to see if the respective page has been rasterised.
	If not, the rasterise() method is invoked, which prepares the
	glyphs from the respective glyph page for being painted.

	This array is big enough to hold at least max_codepoint bits.
	If this member is NULL, all glyphs are considered pre-rasterised.
	*/
	UINT*		m_glyphPageLoaded;

	//! Type definition for ImagesetVector.
	typedef std::vector<HTEXTURE> TextureVector;
	//! Textures that holds the glyphs for this font.
	mutable TextureVector m_glyphImages;

protected:
	// Update the font as needed, according to the current parameters.
	bool		UpdateFont();
	// Set the maximal glyph index. This reserves the respective number of bits in the d_glyphPageLoaded array.
	void		SetMaxCodepoint(UINT32 codepoint);
	/*return
	Pointer to the glyphDat struct for \a codepoint, or 0 if no glyph
	is defined for \a codepoint.
	*/
	hgeFontGlyph* GetGlyphData(UINT32 codepoint);

	/*!
	\brief
	This function prepares a certain range of glyphs to be ready for
	displaying. This means that after returning from this function
	glyphs from d_cp_map[start_codepoint] to d_cp_map[end_codepoint]
	should have their d_image member set. If there is an error
	during rasterisation of some glyph, it's okay to leave the
	d_image field set to NULL, in which case such glyphs will
	be skipped from display.
	\param start_codepoint
	The lowest codepoint that should be rasterised
	\param end_codepoint
	The highest codepoint that should be rasterised
	*/
	virtual void Rasterise(UINT32 start_codepoint, UINT32 end_codepoint);

	/*return
	pixel spacing from top of front glyphs to baseline
	*/
	float GetBaseline(float y_scale = 1.0f) { return m_ascender * y_scale; }

	/*!
	\brief
	Return the required texture size required to store imagery for the
	glyphs from s to e
	\param s
	The first glyph in set
	\param e
	The last glyph in set
	*/
	UINT GetTextureSize(CodepointMap::iterator s,	CodepointMap::iterator e) const;

	/*!
	\brief
	Copy the current glyph data into \a buffer, which has a width of
	\a buf_width pixels (not bytes).

	\param buffer
	Memory buffer large enough to receive the imagery for the currently
	loaded glyph.

	\param buf_width
	Width of \a buffer in pixels (where each pixel is a argb_t).

	\return
	Nothing.
	*/
	void DrawGlyphToBuffer(UINT32* buffer, UINT buf_width) const;
};


#endif
